namespace Legend.IoCo
{
    using System;

    public static class As
    {
        public static Func<IComponentResolver, T> Singleton<T>(this Func<IComponentResolver, T> creator)
        {
            return new SingletonResolver<T>(creator).GetInstance;
        }

        private class SingletonResolver<T>
        {
            private IState state;

            public SingletonResolver(Func<IComponentResolver, T> creator)
            {
                this.state = new UnresolvedState(creator, this);
            }

            private interface IState
            {
                T GetInstance(IComponentResolver resolver);
            }

            public T GetInstance(IComponentResolver resolver)
            {
                return this.state.GetInstance(resolver);
            }

            private class UnresolvedState
                : IState
            {
                private Func<IComponentResolver, T> creator;
                private SingletonResolver<T> parent;

                public UnresolvedState(Func<IComponentResolver, T> creator, SingletonResolver<T> parent)
                {
                    this.creator = creator;
                    this.parent = parent;
                }

                public T GetInstance(IComponentResolver resolver)
                {
                    var result = this.creator.Invoke(resolver);
                    this.parent.state = new ResolvedState(result);
                    return result;
                }
            }

            private class ResolvedState
                : IState
            {
                private T instance;

                public ResolvedState(T instance)
                {
                    this.instance = instance;
                }

                public T GetInstance(IComponentResolver resolver)
                {
                    return this.instance;
                }
            }
        }
    }
}
